#ifndef __MP3DECODER_HPP__
#define __MP3DECODER_HPP__

#include <stdint.h>
#include <sys/types.h>
#include <functional>
#include <mad.h>
#include <foundation.hpp>
#include <semaphore.h>
#include "ring_buf.h"
#include "DecoderBase.hpp"

#define LIBMAD_INPUT_BUF_LEN     (2 * 1024)     //送给libmad的缓存



class Mp3Decoder;

typedef std::function<void(Mp3Decoder *player)> Mp3DecoderStateChageCB;

class Mp3Decoder
{
private:
    FRunLoop *runLoop;
    pthread_t th;
    struct mad_decoder decoder;
    ring_buf           cache;
    uint8_t     *pcmBuffer;
    uint8_t     libmad_input_buf[LIBMAD_INPUT_BUF_LEN];
    sem_t       sem_produce;
    pthread_mutex_t   mutex;
    FEvent *notifyPCMInfoEvent = nullptr;
    FEvent *havePCMEvent = nullptr;
    FEvent *finishEvent = nullptr;
    bool postedDestroy = false;
    bool pcmCacheEmpty = false;
public:
    enum State {
        IDLE,
        LOADING,
        WORKING,
        FINISH,
    };
    enum Error {
        UNABLE_OPEN_FILEPATH,
        STATE_ERR,
        NO_MEM,
    };
private:
    char *filePath;
    int fileFd;
    State state;
    AudioPCMInfo pcmInfo;
    bool interrupt = false;
    ~Mp3Decoder();
    void createThread();
public:
    Mp3DecoderStateChageCB stateChangeCB;
    Error recentError;
    Mp3Decoder(FRunLoop *runLoop, const char *path);
    State getState();
    static const char *stateToString(State state);
    bool start();
    void seekTo(int ms);

    const AudioPCMInfo *getPCMInfo();
    int readPCM(int16_t *pcm, int len);
    void destroy();
    void printCache();
};

#endif